package General;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
import java.util.Scanner;

import Building.Wonder;

public class Game implements Observer{
    /**
     * @param args
     */
    private int playerCount;
    public Player[] players;    	//Need some container to hold players
    Bank bank;            	//The central bank, holds resources to be circulated
    public static Game currentGame;
    public static UI currentUI;
    public static final boolean UI = false;            //false for CLI, true for GUI
    public static final int MIN_PLAYERS = 2;
    public static final int MAX_PLAYERS = 9;
    public static boolean victory = false;            //global flag, when set game will halt next cycle
    private int currentPlayer;
    private int startingPlayer;
   
    public static void main(String[] args) {
    	Culture.initializeCard();
    	Game currentGame = new Game();			//start the game
    	currentGame.currentUI = new UI();
        currentGame.currentUI.programIntro(); 	//Displays purpose of the program
        // Setup players
        currentGame.requestPlayers();
        currentGame.bank = Bank.createBank(currentGame.playerCount);
        Bank.singletonBank.addObserver(currentGame);
        currentGame.initializePlayers();
        currentGame.runGame(currentGame);
    }//end main
    public void runGame(Game currentGame){        
		int mode=-1;
		do{
			switch(mode){
			case -1: //setup
				startingPlayer = Dice.determineStarting(playerCount);
				currentPlayer = startingPlayer;
				mode++;
				break;
			case 0:	// assign victory points
				int	end = playerCount==2?2:3;	//if there are only 2 players only assign 2 pts 
				for(int i =0; i<end; i++){
					Bank.singletonBank.placeVictory(VictoryCards.fromInt(
						currentUI.assignVictory(this.players[currentPlayer])));
					nextPlayer();
					currentUI.padOut();
				}
				mode++;
				break;
			case 1:
				//Draw Action cards
				currentPlayer = startingPlayer;
				for(int i = 0; i < playerCount; i++){
					int currentCard=0;
					boolean drawComplete = false;
					boolean randMode= false;
					while(!drawComplete){
						if(!players[currentPlayer].handFull()){	//check to see if player can draw
							if(!randMode){
								currentCard= currentUI.drawCard(players[currentPlayer]);
								currentCard -=1;	//account for the display-backend numbering scheme disparity;
							}else {
								currentCard= currentUI.drawRandom(players[currentPlayer]);
								currentCard = currentCard==0?-1:7;	//choices are limited to -1 random, 7 pass
							}
							
							if(currentCard ==-1){	//whenever a random card is drawn state changes to random only
								randMode= true;
								players[currentPlayer].draw(currentCard);
							} else if(currentCard == 7){	//player wishes to pass
								if(players[currentPlayer].handCount()<3){
									currentUI.notifyEmptyHand(players[currentPlayer]);
								} else drawComplete = true;
							} else {	//normal card drawing procedure
								players[currentPlayer].draw(currentCard);
							}
						}else {
							currentUI.notifyFullHand(players[currentPlayer]);
							drawComplete = true;
						}
						currentUI.padOut();
					}
					nextPlayer();
				}
				mode++;
				break;
			case 2:	//Action card play
				currentPlayer= startingPlayer;
				
				mode++;
				break;
			case 3: // Spoilage
				currentPlayer= startingPlayer;
				for(int i = 0; i< playerCount; i++){
					Resource before = players[currentPlayer].getWallet().getFunds();
					players[currentPlayer].spoil();
					Resource after = players[currentPlayer].getWallet().getFunds();
					currentUI.spoilageA(players[currentPlayer], before, after);
					currentUI.padOut();
					nextPlayer();
				}
				mode++;
				break;
				
			case 4: // Discard
				currentPlayer = startingPlayer;
				for(int i = 0; i< playerCount; i++){
					
				}
			default: //In case an option not listed is selected
				System.out.println("Bad Game State");
				victory= true;
				break;
			}	//end switch
			
		}while (Game.victory==false);
			
    }//end runGame
    
    public int getPlayerCount()
    {
        return playerCount;
    }//end getPlayerCount
   
    private void setPlayerCount(int players)
    {
        playerCount=players;
    }//end setPlayercount
   
    private void requestPlayers()
    {
        setPlayerCount(currentUI.getBoundedInt("Number of players: ",2,9));
    }//end request Players
   
   
    private void initializePlayers(){
        int count = getPlayerCount();
        String name= null;
        Scanner scn = new Scanner(System.in);
        players = new Player[count];
        LinkedList<Integer> cultures = Dice.chooseCulture(count);
        int index = 0;
        while(!cultures.isEmpty() && index < count){    //copy values to array
            players[index] = new Player(cultures.pop());
            System.out.println ("State your name Player " + index + ": ");
            name= scn.nextLine();
            players[index].setName(name);
            index++;
        }//end while-loop
    }//end initialize players
   
   

    public void drawActionCards(Player player)
    {
       
    }//end method
   
   
    public void setVictory(){
        victory= true;
    }
    private void nextPlayer(){
    	currentPlayer= (currentPlayer + 1)%playerCount;
    }
    private void rotateStarting(){
    	startingPlayer = (startingPlayer +1)%playerCount;
    }
    /**
     * This observer observes the value of the victory points left in the bank.  
     * If the bank runs out of victory points, the game is over 
     */
	@Override
	public void update(Observable o, Object arg) {
		// TODO not enought time to implement proper generics/ type safety 
		Integer a = (Integer)arg;
		if (a.compareTo(new Integer(0))<=0){
			victory= true;
		}
	}
   
}//end class Game